package fi.internetix.ck;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;

public class HTMLCleanup {

  public String cleanupHTML(String htmlData) throws Exception {
    
    // As good as Tidy is, it seems to have occasional problems parsing script and style
    // tags into a DOM so let's just regexp them out of the way first 
    
    htmlData = htmlData.replaceAll("(?is)<s(cript|tyle).*?>.*?</s(cript|tyle).*?>", "");
    
    // Let Tidy work its magic to get a decent DOM model of the data
    
    Tidy tidy = new Tidy();

    tidy.setXHTML(true); // output extensible HTML.
    tidy.setWord2000(true); // draconian cleaning for Word2000.
    tidy.setMakeBare(true); // remove Microsoft cruft.
    tidy.setQuoteNbsp(false); // output non-breaking space as entity.
    tidy.setAsciiChars(true); // convert quotes and dashes to nearest ASCII char.
    tidy.setMakeClean(true); // remove presentational clutter
    tidy.setTrimEmptyElements(true); // trim empty elements.
    tidy.setDropEmptyParas(true); // discard empty p elements.
    tidy.setDropFontTags(true); // discard presentation tags.
    tidy.setFixComments(true); // fix-bad-comments- fix comments with adjacent hyphens.
    tidy.setHideComments(true); // hides all (real) comments in output.
    tidy.setJoinStyles(true); // join multiple style attributes.

    tidy.setInputEncoding("UTF-8"); // input encoding
    tidy.setQuiet(true); // don't output summary, warnings or errors
    tidy.setShowWarnings(false); // show-warnings
    tidy.setForceOutput(true); // output document even if errors were found.
    tidy.setPrintBodyOnly(true); // output BODY content only.
    
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    tidy.parse(new ByteArrayInputStream(htmlData.getBytes("UTF-8")), baos);
    baos.flush();
    baos.close();
    Document doc = tidy.parseDOM(new ByteArrayInputStream(baos.toByteArray()), null);

    // Print out the DOM with the aid of various NodePrinters stripping
    // out unwanted elements
    
    NodeList children = doc.getDocumentElement().getChildNodes();
    StringBuilder output = new StringBuilder();
    for (int i = 0; i < children.getLength(); i++) {
      Node child = children.item(i);
      NodePrinter nodePrinter = NodePrinterUtils.getNodePrinter(child);
      if (nodePrinter != null) {
        nodePrinter.processNode(child, output);
      }
    }

    return output.toString();
  }

}
